home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 6
/
MacMania 6.toast
/
/
Multimedia & Desktop
/
VideoToolbox
/
VideoToolboxSources
/
SetPriority.c
< prev
next >
Wrap
Text File
|
1997-07-02
|
7KB
|
179 lines
/*
SetPriority.c
SetPriority(1);
// do high priority stuff here
SetPriority(0);
Get and set the processor priority. The Macintosh operating system
normally leaves the processor priority at zero, allowing all interrupts.
You can temporarily block interrupts by raising the processor priority.
The highest level is 7, blocking all interrupts. This is useful for time
critical tasks, such as running video animations, where your primary
concern is video timing, and you're willing to miss AppleTalk and
keyboard events. Note that while the processor priority is high the
keyboard and mouse will be dead, so that it is essential that your
program lower it back down to allow the user to regain control.
Note that it may be enough to raise priority from the normal 0 to 1,
because that blocks all deferred tasks until you take priority back down
to 0. See the Deferred Task Manager in the Inside Mac Processes book.
It's a strange fact, but interrupt priority on PPC Macs is controlled
by the processor priority of the emulated 68K processor. And the only
way to set or get the processor priority is to run (possibly emulated)
68K code that accesses the 68K Status Register, as we do here using the
inline functions GetStatusRegister() and SetStatusRegister().
Apple's Technote 1001 explains that processor priority is not hardware
implemented in the PowerPC and that in fact there is no legal way to set
it from PPC code. The suggested work-around, for old code, is to call a
bit of 68K code since the 68K emulator will then do the right thing,
setting the effective priority. That's what we do here. When compiled as
PowerPC code the function calls a 68K version of the routines to actual
get and set the priority. Technote 1094 (on VM) gives some details about
emulation of the priviledged 68K instructions that access the SR.
SetPriority and GetPriority are trivial and fast when compiled as 68K
code. They incur the cost of a mixed-mode switch (to and fro) when
run as PPC code, because the actual set/get of priority can only be done
as 68K code. I think the mixed mode switch takes on the order of 100
microseconds, but that's only a vague recollection.
SEE:
http://devworld.apple.com/dev/technotes/tn/tn1001.html
<http://devworld.apple.com/dev/technotes/tn/tn1094.html>
http://devworld.apple.com/dev/techsupport/insidemac/PPCSoftware/PPCSoftware-14.html
ACKNOWLEDGEMENTS:
Thanks for help from:
Quinn "The Eskimo!" <http://devworld.apple.com/dev/geeks.html> 421080
Bo3b Johnson, Apple Developer Technical Support 421080
HISTORY:
1989? dgp wrote it
8/1/91 dgp introduced the inline functions as a way to isolate the machine code
part, and to make it compatible with MPW C as well as THINK C.
8/6/91 dgp fixed definition of GetStatusRegister() to make it a legal prototype.
2/15/93 dgp added SwapPriority().
7/29/94 dgp disable all code if compiling for PowerPC
4/13/97 dgp Made callable from PowerPC code.
4/15/97 dgp Mention deferred tasks.
4/17/97 dgp MakeDataExecutable
4/28/97 dgp Deleted an erronous comment above about User/Supervisor mode.
*/
#include "VideoToolbox.h"
#if GENERATING68K
/* 68k inline functions supported by THINK, MPW, and CodeWarrior C. */
pascal short GetStatusRegister(void)=0x40d7; /* MOVE.W SR,(SP) */
pascal void SetStatusRegister(short status)=0x46df; /* MOVE.W (SP)+,SR */
#else
#include <OSUtils.h> // FlushCodeCacheRange
/* 68K code, as compiled by CodeWarrior C. */
short SetPriority68K[]=
{0x48E7,0x1800,0x282F,0x000C,0x7007,0xC880,0xE18C,0x554F
,0x40D7,0x301F,0x3600,0x0243,0xF8FF,0x8644,0x3F03,0x46DF,0x4CDF
,0x0018,0x4E74,0x0004,0x8B53,0x4554,0x5052,0x494F,0x5249,0x5459,0x0000};
short GetPriority68K[]=
{0x2F03,0x7600,0x554F,0x40D7,0x301F,0x3600,0xE043
,0x0243,0x0007,0x3003,0x48C0,0x2F40,0x0008,0x261F
,0x4E75,0x8B47,0x4554,0x5052,0x494F,0x5249,0x5459,0x0000};
enum {
setPriority68KProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
,getPriority68KProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long)))
};
#endif
pascal void SetPriority(long i)
{
#if GENERATING68K
register short status;
i &= 7;
i <<= 8;
status=GetStatusRegister();
status &= ~0x700; // clear the priority bits
status |= i; // insert new priority bits
SetStatusRegister(status);
#else
static Boolean firstTime=1;
if(firstTime){
MakeDataExecutable(SetPriority68K,sizeof(SetPriority68K));
firstTime=0;
}
CallUniversalProc((UniversalProcPtr)SetPriority68K,setPriority68KProcInfo,i);
#endif
}
pascal long GetPriority(void)
{
register short status=0;
#if GENERATING68K
status=GetStatusRegister();
status >>= 8;
status &= 7;
#else
static Boolean firstTime=1;
if(firstTime){
MakeDataExecutable(GetPriority68K,sizeof(GetPriority68K));
firstTime=0;
}
status=CallUniversalProc((UniversalProcPtr)GetPriority68K,getPriority68KProcInfo);
#endif
return status;
}
void SwapPriority(char *priority)
{
char oldPriority;
oldPriority=GetPriority();
SetPriority(*priority);
*priority=oldPriority;
}
/*
Compiled without A6 Stack frames (linker option) because the Linker won't get to
fix up the zero field left by the compiler.
Hunk: Kind=HUNK_GLOBAL_CODE Name="SETPRIORITY"(1) Size=54
00000000: 48E7 1800 MOVEM.L D3/D4,-(A7)
00000004: 282F 000C MOVE.L $000C(A7),D4
00000008: 7007 MOVEQ #$07,D0
0000000A: C880 AND.L D0,D4
0000000C: E18C LSL.L #$8,D4
0000000E: 554F SUBQ.W #$2,A7
00000010: 40D7 MOVE SR,(A7)
00000012: 301F MOVE.W (A7)+,D0
00000014: 3600 MOVE.W D0,D3
00000016: 0243 F8FF ANDI.W #$F8FF,D3
0000001A: 8644 OR.W D4,D3
0000001C: 3F03 MOVE.W D3,-(A7)
0000001E: 46DF MOVE (A7)+,SR
00000020: 4CDF 0018 MOVEM.L (A7)+,D3/D4
00000024: 4E74 0004 RTD #$0004
00000028: 8B53 4554 5052 DC.B $80+$0B, 'SETPRIORITY'
494F 5249 5459
00000034: 0000
Hunk: Kind=HUNK_GLOBAL_CODE Name="GETPRIORITY"(2) Size=44
00000000: 2F03 MOVE.L D3,-(A7)
00000002: 7600 MOVEQ #$00,D3
00000004: 554F SUBQ.W #$2,A7
00000006: 40D7 MOVE SR,(A7)
00000008: 301F MOVE.W (A7)+,D0
0000000A: 3600 MOVE.W D0,D3
0000000C: E043 ASR.W #$8,D3
0000000E: 0243 0007 ANDI.W #$0007,D3
00000012: 3003 MOVE.W D3,D0
00000014: 48C0 EXT.L D0
00000016: 2F40 0008 MOVE.L D0,$0008(A7)
0000001A: 261F MOVE.L (A7)+,D3
0000001C: 4E75 RTS
0000001E: 8B47 4554 5052 DC.B $80+$0B, 'GETPRIORITY'
494F 5249 5459
0000002A: 0000
*/